package Study2;

/*抽象类
一个方法如果被 abstract 修饰，那么这个方法就是抽象方法，抽象方法。抽象方法可以没有
具体的实现
1.抽象类不可以被实例化，不能 new
2.类内的数据成员，和普通类没有区别
3.抽象类主要就是用来被继承的
4.如果一个类继承了这个抽象类，那么这个类必须重写抽象类当中的
注意：抽象方法不可以被 final 修饰的，因为被 final修饰的方法是不可以被重写的
* */


abstract class Shape {  // 抽象类
    public int age;
    public void func() {

    }

    public abstract void draw();  // 抽象方法
}

class React extends Shape {
    // 继承抽象类，需要对抽象类中的抽象方法重定 —— 动态绑定

    @Override
    public void draw() { // 快捷键 Ctrl + i
        System.out.println("画一个 🔺");
    }
}


class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("画一个 🔴");
    }
}



/*接口：
1.接口当中的方法，都是抽象方法
2.其实可以有具体的实现方法，这是在 JDK8加入的
3.接口当中的成员变量默认是 public static final 就算你不写也是该，定义的常量,
成员默认方法是：public abstract void 的抽象方法，所以必须重写
4.接口是不可以被实例化的
5.接口和类之间的关系：implements (实现接口的意思) 因为接口中的方法是抽象方法，所以在实现上是要
对抽象方法，进行重写的
6.为了解决 Java中的单继承的问题,可以实现多个接口
* */

interface Shape1 {
    void draw();  // 成员方法，默认是 public abstract 抽象类
}

class Cycle implements Shape1 {
    @Override
    public void draw() {
        System.out.println("画一个🔴");
    }
}


class React1 implements Shape1 {
    @Override
    public void draw() {
        System.out.println("画一个 🔺");
    }
}




// 多个接口的使用实例
class Animal {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }
}

// 实现一组接口 分别表示 会飞,会跑,会游泳
interface IFlying { // 接口的定义
    void fly(); // 默认的抽象方法: public abstract 的
}

interface IRuning { // 接口的定义
    void run();  // 默认的抽象方法：public abstract
}

interface Iswimming { // 接口的定义
    void swim();  // 默认的抽象方法：public abstract
}

// 具体的动物实现 继承加接口的实现
class Cat extends Animal implements IRuning {
    public Cat(String name) {
        super(name); // 构造方法
    }
    @Override // 重写 注解：提示错误，人和编译器都可以读懂的注释
    public void run() { // 接口中的抽象方法的重写 —— 动态绑定
        System.out.println(this.name+" 会跑");
    }
}


class Fish extends Animal implements Iswimming {
    public Fish(String name) {
        super(name); // 调用父类的构造方法，放在第一行，只有一个
    }

    @Override
    public void swim() {
        System.out.println(this.name + "会游泳");
    }
}


// 青蛙是会跑，会游泳的动物,两个接口实现，所以这两个接口的抽象方法都需要重写
class Frog extends Animal implements Iswimming,IRuning {
    public Frog(String name) {
        super(name);
    }

    @Override
    public void swim() {
        System.out.println(this.name+" 会游泳");
    }

    @Override
    public void run() {
        System.out.println(this.name+ " 会跑");
    }

}
public class Study20 {

    public static void runs(IRuning iRuning) {
        iRuning.run();
    }

    public static void swims(Iswimming iswimming) {
        iswimming.swim();
    }

    public static void walk(IRuning iRuning) {
        System.out.println("散步");
        iRuning.run();
    }
    public static void main(String[] args) {
        Cat cat = new Cat("猫");
        runs(cat);

        Fish fish = new Fish("飞鱼");
        swims(fish);

        Frog frog = new Frog("青蛙");
        runs(frog);
        swims(frog);
        walk(cat);
        walk(frog);


      /*  Animal animal = new Cat("test");
        runs(animal);
        对接口的使用：接口无法实例化，子类的实例化，并实现了对应的接口，通过接口的类型的访问，来调用接口，
        只有对接口的实现了，才可以通过接口调用接口中的抽象类，重写*/

    }



    public static void main3(String[] args) {
        Shape1 shape1 = new Cycle();
        Shape1 shape11 = new React1();
        shape1.draw();
        shape11.draw();
    }

    public static void func(Shape shape) {
        shape.draw();
    }

    public static void main2(String[] args) {
        Shape shape1 = new React();
        Shape shape2 = new Circle(); // 向上转型，父类引用子类的对象
        func(shape1);
        func(shape2);

    }

    public static void main1(String[] args) {
//        Shape shape = new Shape();// 注意 抽象类是不可以被实例化的，通过继承，子类的方式，实例化

        Shape shape = new React();  // 向上转型，父类引用子类的对象
        Shape shape1 = new Circle();
        shape.draw();
        shape1.draw(); // 重写，动态绑定
    }


}
